package com.example.JavaWebApi.service.impl.systemImpl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.JavaWebApi.core.apiinterceptors.Enum.RoleEnum;
import com.example.JavaWebApi.core.commonmodel.Exceptions.BusinessException;
import com.example.JavaWebApi.core.commonmodel.ResponseTypeEnum;
import com.example.JavaWebApi.core.reflect.ReflectionHelper;
import com.example.JavaWebApi.mapper.systemMapper.DictionaryMapper;
import com.example.JavaWebApi.model.entity.systemEntity.Dictionary;
import com.example.JavaWebApi.service.systemService.IDictionaryService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @program: adks.process-api
 * @description:
 * @author: 杨泽
 * @create: 2022-05-05 17:00
 */
@Service
public class DictionaryServiceImpl extends ServiceImpl<DictionaryMapper, Dictionary> implements IDictionaryService {
    private static final Object locker=new Object();
    @Override
    public List<Dictionary> getListByParentId(int parentId) {
        QueryWrapper<Dictionary> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("ParentID",parentId)
                .eq("IsDelete",0)
                .orderByDesc("SortNo");
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<Dictionary> getTreeList() {
        QueryWrapper<Dictionary> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("IsDelete",0)
                .orderByDesc("SortNo");
        List<Dictionary> list=this.baseMapper.selectList(queryWrapper);
        return ReflectionHelper.convertToTreeList(list,t->t.getParentId()==null||t.getParentId().equals(0),t->t.getId(),t->t.getParentId(),Dictionary.class);

    }

    @Override
    public IPage<Dictionary> getLazyNode(Integer parentId, int page, int limit) {
        QueryWrapper<Dictionary> queryWrapper=new QueryWrapper<>();
        queryWrapper.select("*,(case when exists(select 1 from sys_dictionary sub where sub.ParentId=sys_dictionary.ID) then 1 else 0 end) as hasChildren");
        if (parentId==null||parentId.equals(0)){
            queryWrapper.and(wrapper->wrapper.apply("ParentID is null or ParentID=0"));
        }
        else {
            queryWrapper.eq("ParentID",parentId);
        }
        queryWrapper.eq("IsDelete",0)
                .orderByDesc("SortNo");
        IPage<Dictionary> pageModel=new Page<>(page,limit);
        return this.baseMapper.selectPage(pageModel,queryWrapper);
    }

    @Override
    public boolean createNode(Dictionary entity) {
        if(entity.getValue().equals(RoleEnum.SuperAdmin.toString())){
            throw new BusinessException(ResponseTypeEnum.Exception,"保留关键字,不允许创建！");
        }
        dataLock(entity);
        return this.baseMapper.insert(entity)>0;
    }
    private void dataLock(Dictionary entity){
        String message=null;
        synchronized (locker){
            QueryWrapper<Dictionary> queryWrapper=new QueryWrapper<>();
            if (entity.getParentId()==null||entity.getParentId().equals(0)){
                queryWrapper.and(wrapper->wrapper.apply("ParentID is null or ParentID=0"));
            }
            else {
                queryWrapper.eq("ParentID",entity.getParentId());
            }
            //修改的时候code不能改
            if (entity.getId()!=0){
                entity.setCode(null);
                queryWrapper.ne("Id",entity.getId());
            }
            else {
                String code=createOrgCode(entity.getParentId());
                entity.setCode(code);
            }
            queryWrapper.eq("IsDelete",0)
                    .eq("`Value`",entity.getValue());
            long count=this.baseMapper.selectCount(queryWrapper);
            if (count!=0){
                message ="同一父节点下不允许存在value相同的节点！";
            }
            if(StringUtils.isNotBlank(message)){
                throw new BusinessException(ResponseTypeEnum.OperationFailed,message);
            }
        }
    }

    @Override
    public boolean updateNode(Dictionary entity) {
        if(entity.getValue().equals(RoleEnum.SuperAdmin.toString())){
            throw new BusinessException(ResponseTypeEnum.Exception,"保留关键字,不允许更新！");
        }
        dataLock(entity);
        return this.baseMapper.updateById(entity)>0;
    }

    @Override
    public boolean deleteNode(int id) {
        Dictionary entity=new Dictionary();
        entity.setIsDelete(1);
        entity.setId(id);
        return this.baseMapper.updateById(entity)>0;
    }
    private String createOrgCode(Integer parentId){
        Dictionary dictionary=this.baseMapper.selectById(parentId);
        QueryWrapper<Dictionary> queryWrapper=new QueryWrapper<>();
        if (parentId==null){
            queryWrapper.apply("ParentID is null or ParentID=0");
            return getCode(queryWrapper);
        }
        else {
            queryWrapper.eq("ParentID", parentId);
            return dictionary.getCode() + getCode(queryWrapper);
        }
    }

    /**
     * Description: 生成字典code 调用此方法必须在调用者上加锁 要不无法保证code的准确性
     * @param queryWrapper
     * @return java.lang.String
     * @author 杨泽
     * @date 2022/6/21 9:29
     */
    private String getCode(QueryWrapper<Dictionary> queryWrapper){
        String code;
        queryWrapper.select("right(max(Code),3) as Code");
        List<Map<String,Object>> maps=this.baseMapper.selectMaps(queryWrapper);
        if (maps.get(0)!=null){
            code=String.valueOf(Integer.valueOf(String.valueOf(maps.get(0).get("Code")))+1);
            while (code.length()<3){
                code="0"+code;
            }
        }
        else {
            code="001";
        }
        return code;
    }
}